/*
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.code.qsecurity.client.activity;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default;

import com.google.code.qsecurity.client.QClientFactory;
import com.google.code.qsecurity.client.event.ForgottenPasswordEvent;
import com.google.code.qsecurity.client.event.LoginFormEvent;
import com.google.code.qsecurity.client.event.OfflineEvent;
import com.google.code.qsecurity.client.event.OnlineEvent;
import com.google.code.qsecurity.client.event.SignupFormEvent;
import com.google.code.qsecurity.client.event.VerificationFormEvent;
import com.google.code.qsecurity.client.ui.LoginView;
import com.google.code.qsecurity.client.ui.LoginView.LoginPresenter;
import com.google.code.qsecurity.client.ui.BaseView;
import com.google.code.qsecurity.shared.ClientGroup;
import com.google.code.qsecurity.shared.QRequest;
import com.google.code.qsecurity.shared.proxy.UserProxy;
import com.google.code.qsecurity.shared.proxy.response.QLoginResponseProxy;
import com.google.code.qsecurity.shared.proxy.response.QResponseProxy;
import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.web.bindery.requestfactory.gwt.client.RequestFactoryEditorDriver;
import com.google.web.bindery.requestfactory.shared.Receiver;

/**
 * Activities are started and stopped by an ActivityManager associated with a container Widget.
 */
public class LoginActivity extends AbstractActivity implements LoginPresenter {
	/**
	 * Used to obtain views, eventBus, placeController.
	 * Alternatively, could be injected via GIN.
	 */
	private QClientFactory clientFactory;
	
	private LoginView view;
	private RequestFactoryEditorDriver<UserProxy, Editor<UserProxy>> editorDriver;
	private QRequest request;
	private EventBus eventBus;
	
	private UserProxy user;

	public LoginActivity(LoginFormEvent event, QClientFactory clientFactory) {
		this.clientFactory = clientFactory;
	}

	@Override
	public void start(AcceptsOneWidget containerWidget, EventBus eventBus) {
		// TODO check if already logged in
		this.eventBus = eventBus;
		this.view = clientFactory.getLoginView();
		editorDriver = view.createEditorDriver();
		refreshRequest();
		view.init(this);
	}

	@Override
	public String mayStop() {
		return null;
	}

	@Override
	public void onStop() {
		editorDriver = null;
	}
	
	public void refreshRequest() {
		request = clientFactory.getRequestFactory().qRequest();
		user = request.create(UserProxy.class);
		editorDriver.edit(user, request);
	}

	@Override
	public void login() {
		view.refresh();
		editorDriver.flush();
		
		// name is not entered at login; enter dummy value for validation
		user.setName("dummy");
		
		// Validate user fields
		Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
		Set<ConstraintViolation<UserProxy>> violations = validator.validate(user,
				Default.class, ClientGroup.class);
		if (!violations.isEmpty()) {
			List<String> errorMessages = new ArrayList<String>();
			for (ConstraintViolation<UserProxy> constraintViolation : violations) {
				errorMessages.add(constraintViolation.getMessage());
			}
			view.displayErrors(errorMessages);
			return;
		}
		
		request.login(user).fire(new Receiver<QLoginResponseProxy>() {

			@Override
			public void onSuccess(QLoginResponseProxy response) {
				List<String> error;
				switch (response.getCode()) {
					case SYSTEM_FAILURE:
						error = new ArrayList<String>();
						error.add(clientFactory.getConstants().i18n_server_error());
						view.displayErrors(error);
						refreshRequest();
						break;
					case EMAIL_NOT_FOUND:
						error = new ArrayList<String>();
						error.add(clientFactory.getConstants().i18n_unregistered_email());
						view.displayErrors(error);
						refreshRequest();
						break;
					case INVALID_PASSWORD:
						error = new ArrayList<String>();
						error.add(clientFactory.getConstants().i18n_incorrect_password());
						view.displayErrors(error);
						refreshRequest();
						break;
					case EMAIL_NOT_VERIFIED:
						error = new ArrayList<String>();
						error.add(clientFactory.getConstants().i18n_unverified_email());
						view.displayErrors(error);
						refreshRequest();
						break;
					case SUCCESS:
						view.exit();
						eventBus.fireEvent(new OnlineEvent(response.getUser(),
								response.getSessionId(), response.getSessionExpiration()));
						break;
				}
			}
			
		});
	}

	@Override
	public void viewSwitched(int index) {
		view.refresh();
		switch (index) {
			case BaseView.LOGIN_TAB_INDEX:
				// TODO there is something wrong here!
				break;
				
			case BaseView.SIGNUP_TAB_INDEX:
				eventBus.fireEvent(new SignupFormEvent(""));
				break;
				
			case BaseView.VERIFICATION_TAB_INDEX:
				eventBus.fireEvent(new VerificationFormEvent(""));
				break;
		}
	}

	@Override
	public void viewClosed() {
		eventBus.fireEvent(new OfflineEvent(user));
	}

	@Override
	public void forgottenPasswordClicked() {
		eventBus.fireEvent(new ForgottenPasswordEvent(user.getEmail()));
	}

}
